﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using CodeCamp.BL.Helpers;
using CodeCamp.BL.Model;

namespace CodeCamp.BL
{
	public partial class CodeCampBL
	{
		public static int AddSession(Session session, Guid userId)
		{
			using (var context = new CodeCampEntities())
			{
				Camp camp = getCamp(context);
				MemberProfile presenter = getMemberProfile(context, userId);
				if (presenter == null || presenter.AllowPublicProfile == false)
				{
					throw new ArgumentException("Presenter must have a profile with 'Allow Public Profile' checked.", "userId");
				}
				session.Speakers.Add(presenter);
				camp.Sessions.Add(session);
				context.AddToSessions(session);
				context.SaveChanges(true);

				return session.SessionID;
			}
		}


		public static void EditSession(Session session, Guid userId)
		{
			using (var context = new CodeCampEntities())
			{
				Session existing = context.Sessions
					.FirstOrDefault(
									s =>
									s.SessionID == session.SessionID
									&& s.Speakers.Any(m => m.UserId == userId));
				if (existing != null)
				{

					//existing.UpdateSimpleValues(session, "SessionID");
					existing.Name = session.Name;
					existing.Excerpt = session.Excerpt;
					existing.Description = session.Description;
					existing.SegmentCount = session.SegmentCount;

					context.SaveChanges();
				}
			}
		}

		public static Session GetSession(int id)
		{
			using (var context = new CodeCampEntities())
			{
				return context.Sessions
					.Include("Tags")
					.Include("Attachments").FirstOrDefault(s => s.SessionID == id);
			}
		}


		public static IEnumerable<SessionDetail> ListSessions()
		{
			using (var context = new CodeCampEntities())
			{
				List<SessionDetail> result = context.Camps
					.Include("Sessions.Speakers")
					.Include("Sessions.Attachments")
					.Include("Sessions.Tags.Track")
					.Include("Sessions.UserSessionInterests")
					.First(c => c.IsActive)
					.Sessions.Select(
									c => new SessionDetail
										{
											Session = c,
											Interest = c.UserSessionInterests.Count,
											Attachments = c.Attachments.Select(
														a => new Attachment
																{
																	AttachmentID = a.AttachmentID,
																	MimeType = a.MimeType,
																	Name = a.Name
																}).ToList()
										}).ToList();
				return result;
			}
		}


		public static void AddInterest(Guid userId, int sessionID)
		{
			using (var context = new CodeCampEntities())
			{
				Session session = context.Sessions.FirstOrDefault(s => s.SessionID == sessionID);
				if (session != null)
				{
					UserSessionInterest interest = UserSessionInterest.CreateUserSessionInterest(sessionID, userId);
					session.UserSessionInterests.Add(interest);
					context.SaveChanges();
				}
			}
		}

		public static bool AddPresenter(int sessionID, string coPresenterEmail)
		{
			using (var context = new CodeCampEntities())
			{
				aspnet_Membership member = context.aspnet_Membership.FirstOrDefault(m => m.Email == coPresenterEmail);
				if (member != null)
				{
					Session session = context.Sessions.FirstOrDefault(
																		s => s.SessionID == sessionID
																			 && !s.Speakers.Any(e => e.UserId == member.UserId));

					if (session != null)
					{
						session.Speakers.Add(context.MemberProfiles.First(p => p.UserId == member.UserId));

						context.SaveChanges();
						return true;
					}
					return false;
				}
				return false;
			}
		}

		public static void SaveSessionAttachment(HttpPostedFileBase uploaded, Guid userId, int sessionID)
		{
			using (var context = new CodeCampEntities())
			{
				// ensure user owns session
				Session session = context.Sessions.FirstOrDefault(
																	s =>
																	s.SessionID == sessionID
																	&& s.Speakers.Any(p => p.UserId == userId));
				if (session == null)
				{
					throw new InvalidOperationException("Not session owner");
				}

				// insert..
				var attachment = new Attachment
									{
										AttachmentID = Guid.NewGuid(),
										MimeType = uploaded.ContentType,
										Name = uploaded.FileName,
										Value = getBytes(uploaded)
									};
				session.Attachments.Add(attachment);

				context.SaveChanges();
			}
		}


		public static void SaveTags(int sessionID, IList<string> tags, Guid userId)
		{

			using (var context = new CodeCampEntities())
			{
				// ensure user owns session
				Session session =
					context.Sessions.Include("Tags").FirstOrDefault(s => s.SessionID == sessionID && s.Speakers.Any(p => p.UserId == userId));
				if (session == null)
				{
					throw new InvalidOperationException("No such session for this user");
				}

				session.Tags.Clear();

				context.SaveChanges();

				if (tags == null || tags.Count == 0)
				{
					return;
				}

				var existing = new List<string>();


				foreach (var name in tags.Select(ti => ti.Trim()))
				{
					var tag = context.Tags.FirstOrDefault(t => t.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase));
					if (tag != null)
					{
						existing.Add(name);
						session.Tags.Add(tag);
					}
					else
					{
						session.Tags.Add(new Tag() { Name = name });
					}
				}


				context.SaveChanges();
			}

		}

		/// <summary>
		/// Get Tag prevelance of current camp for tag cloud
		/// </summary>
		/// <returns></returns>
		public static Dictionary<string, int> TagUsage()
		{
			using (var context = new CodeCampEntities())
			{
				var tagsWithCount = context.Tags
					.Where(t => t.Sessions.Any(s => s.Camp.IsActive))
					.Select(r => new { r.Name, Number = r.Sessions.Count });

				return tagsWithCount.ToDictionary(a => a.Name, b => b.Number);
			}
		}

		/// <summary>
		/// Session interest of current camp for tag cloud
		/// </summary>
		/// <returns></returns>
		public static Dictionary<string, int> SessoinInterest()
		{
			using (var context = new CodeCampEntities())
			{
				var sessoinInterest = context.Sessions
					.Where(s => s.Camp.IsActive)
					.Select(r => new { r.Name, Number = r.UserSessionInterests.Count });

				return sessoinInterest.ToDictionary(a => a.Name, b => b.Number);
			}
		}

		public static Dictionary<string, List<SessionDetail>> ListByTrack(string filter, string unassignedName)
		{
			var result = new Dictionary<string, List<SessionDetail>>();

			var detail = ListSessions();

			if (!string.IsNullOrEmpty(filter))
			{
				if (filter != unassignedName)
				{
					detail = detail.Where(sd => sd.Session.Tags.Any(t => t.Track != null && t.Track.Name == filter));
				}
				else
				{
					detail = detail.Where(sd => sd.Session.Tags.All(t => t.Track == null));
				}
			}

			foreach (var session in detail)
			{
				Tag trackTag = session.Session.Tags.FirstOrDefault(t => t.Track != null);
				string trackName = (trackTag != null) ? trackTag.Track.Name : unassignedName;
				if (!result.ContainsKey(trackName))
				{
					result[trackName] = new List<SessionDetail>();

				}
				result[trackName].Add(session);
			}
			return result;
		}
	}
}